import { ControlVOBase, deepCopy } from '@/core';
import {
	IReportPanelControllerParams,
	IPanelModel,
	IParam,
	IHttpResponse,
	ICtrlActionResult,
	IActionResult,
} from '@/core/interface';
import {
	IPanelAbility,
	IReportPanelAbility,
} from '@/core/interface/widgets/ability';
import { IReportPanelController } from '@/core/interface/widgets/controller';
import { ReportPanelActionType } from '@/core/interface/widgets/event';
import { IReportPanelStore } from '@/core/interface/widgets/store';
import ReportPanelService from '@/core/modules/ctrl-service/report-panel-service';
import { MDCtrlController } from './md-ctrl-controller';

/**
 *  报表面板控制器
 * 	识别控件动态参数(CONFIG: dst相关配置; DATASOURCE:数据源,DST or DEFAULT，标准可以不用配置,AGGMODE:聚合模式 SUM or NONE)
 *  "CONFIG" : "{'requestUrl':'/lite/report/22a6f22982ce486f38309fed3736ddf2/${person}','searchParams':{'startTime':'xxx','endTime':'xxx',person:'xxx'}}",
 *  "DATASOURCE" : "DST"
 *  "AGGMODE": "SUM" | "NONE"
 *
 * @export
 * @class ReportPanelController
 * @extends {(MDCtrlController<ReportPanelActionType, IReportPanelStore, IReportPanelAbility>)}
 * @implements {IReportPanelController<IReportPanelStore, IReportPanelAbility>}
 * @template A
 */
export class ReportPanelController
	extends MDCtrlController<
		ReportPanelActionType,
		IReportPanelStore,
		IReportPanelAbility
	>
	implements IReportPanelController<IReportPanelStore, IReportPanelAbility>
{
	/**
	 * 面板模型
	 *
	 * @protected
	 * @type {IPanelModel}
	 * @memberof ReportPanelController
	 */
	protected declare readonly model: IPanelModel;

	/**
	 * 自定义参数
	 *
	 * @protected
	 * @type {(IParam | undefined)}
	 * @memberof ReportPanelController
	 */
	protected customParams: IParam | undefined = undefined;

	/**
	 * 部件服务
	 *
	 * @type {ReportPanelService<ControlVOBase>}
	 * @memberof ReportPanelController
	 */
	declare ctrlService: ReportPanelService<ControlVOBase>;

	/**
	 * Creates an instance of ReportPanelController.
	 * @param {IReportPanelControllerParams} params
	 * @memberof ReportPanelController
	 */
	public constructor(
		params: IReportPanelControllerParams<
			ReportPanelActionType,
			IReportPanelAbility
		>
	) {
		super(params);
		this.customParams = params.customParams;
		this.ctrlInit(params);
	}

	/**
	 * 处理部件初始化
	 *
	 * @protected
	 * @param { IReportPanelControllerParams<ReportPanelActionType, IReportPanelAbility>} params
	 * @memberof ReportPanelController
	 */
	protected processCtrlInit(
		params: IReportPanelControllerParams<
			ReportPanelActionType,
			IReportPanelAbility
		>
	) {
		super.processCtrlInit(params);
		Object.assign(this.store, {
			data: {},
			enableDesign: import.meta.env.DEV,
		});
	}

	/**
	 * 加载数据
	 *
	 * @param {IParam} [opts={}]
	 * @return {*}  {Promise<ICtrlActionResult>}
	 * @memberof ReportPanelController
	 */
	public async load(opts: IParam = {}): Promise<ICtrlActionResult> {
		const { context, viewParams, limit } = this.store;
		const { fetchAction } = this.actions;
		if (!fetchAction) {
			console.warn(App.ts('widget.md.notconfig.fetchaction', '未配置加载行为'));
			return { ok: false, data: this.getData(), rowData: { status: 500 } };
		}
		if (opts && opts.srfpagereset) {
			this.store.curPage = 1;
			delete opts.srfpagereset;
		}
		const { paging, noSort, sortDir, sortField, name } = this.model;
		const arg: any = {};
		const queryParams: IParam = {};
		//  开启分页
		if (paging) {
			Object.assign(queryParams, { page: this.store.curPage - 1, size: limit });
		}
		//  排序
		if (!noSort && !opts.srfsortreset) {
			if (opts.sort) {
				Object.assign(queryParams, { sort: opts.sort });
			} else {
				if (sortField) {
					Object.assign(queryParams, {
						sort: `${sortField},${sortDir ? sortDir : 'asc'}`,
					});
				}
			}
		}
		delete opts.srfsortreset;
		const parentData: IParam = {};
		this.emit('beforeLoad', [parentData]);
		//	视图查询参数
		if (parentData && Object.keys(parentData).length > 0) {
			Object.assign(queryParams, parentData);
		}
		//	额外查询参数
		if (opts && Object.keys(opts).length > 0) {
			Object.assign(queryParams, opts);
		}
		const tempViewParams = Object.assign(deepCopy(viewParams), queryParams);
		Object.assign(arg, { viewParams: tempViewParams });
		const tempContext = deepCopy(context);
		const res = await this.beforeAsyncAction('load', tempContext, arg);
		if (!res.ok) {
			return { ok: false, data: this.getData(), rowData: { status: 500 } };
		}
		// 合并界面逻辑执行参数
		if (res.data && res.data.length > 0) {
			Object.assign(arg, res.data[0]);
		}
		try {
			const response: IHttpResponse = await this.ctrlService.search(
				fetchAction,
				tempContext,
				arg
			);
			if (!response.success) {
				await this.afterAsyncAction('load', response);
				return {
					ok: false,
					data: this.getData(),
					rowData: response,
				};
			}
			const res = await this.afterAsyncAction('load', response);
			if (!res.ok) {
				return { ok: false, data: this.getData(), rowData: { status: 500 } };
			}
			const { total } = response as IParam;
			if (total || total === 0) {
				this.store.totalRecord = total;
			}
			this.handleLoadDataChange(response.data);
			this.store.isLoaded = true;
			this.emit('load', response.data);
			return {
				ok: true,
				data: this.getData(),
				rowData: response,
			};
		} catch (error: any) {
			await this.afterAsyncAction('load', error);
			return {
				ok: false,
				data: this.getData(),
				rowData: error,
			};
		}
	}

	/**
	 * 异步行为之后
	 *
	 * @param {string} action
	 * @param {IHttpResponse} response
	 * @return {*}  {Promise<IActionResult>}
	 * @memberof ReportPanelController
	 */
	public async afterAsyncAction(
		action: string,
		response: IHttpResponse
	): Promise<IActionResult> {
		const { loadingHelper } = this.store;
		loadingHelper.endLoading();
		if (response && response.success === false) {
			App.getNotificationHelper().error(
				App.ts('common.generic.error'),
				response.message || ''
			);
		}
		if (this.UIEngineContainer) {
			const _action =
				'on' + action.toLowerCase() + (response.success ? 'success' : 'error');
			const inputParam = this.getUIEngineInputParam({ data: response.data });
			return await this.UIEngineContainer.executeCtrlEvent(_action, inputParam);
		} else {
			return { ok: true, data: [response] };
		}
	}

	/**
	 * 处理加载数据变化
	 *
	 * @protected
	 * @param {IParam[]} data
	 * @memberof ReportPanelController
	 */
	protected handleLoadDataChange(data: IParam[] | IParam) {
		// 声明结果值
		let result: any = {};
		// 计算目标数据
		const targetData = this.computeTarget(data);
		// 存在报表模板编译模板
		if (this.model.reportModel) {
			const template = Handlebars.compile(this.model.reportModel);
			const targetStr = template(targetData);
			result = targetStr ? eval(`(${targetStr})`) : {};
		}
		// 绑定结果值
		this.store.data = result;
	}

	/**
	 * 计算目标值
	 *
	 * @private
	 * @param {(IParam[] | IParam)} data
	 * @return {*}
	 * @memberof ReportPanelController
	 */
	private computeTarget(data: IParam[] | IParam) {
		let targetData: any;
		// DST
		if (
			this.customParams &&
			this.customParams.DATASOURCE &&
			this.customParams.DATASOURCE === 'DST'
		) {
			const sourceData = data as IParam;
			targetData = {};
			if (this.customParams.AGGMODE && this.customParams.AGGMODE == 'SUM') {
				if (sourceData.rows && sourceData.rows.length > 0) {
					sourceData.rows.forEach((element: IParam) => {
						if (Object.keys(targetData).length === 0) {
							Object.assign(targetData, element);
						} else {
							Object.keys(targetData).forEach((key: string) => {
								targetData[key] += element[key];
							});
						}
					});
				}
			} else {
				return sourceData.rows;
			}
		} else {
			// 常规
			targetData = data;
		}
		return targetData;
	}

	/**
	 * 获取部件能力
	 *
	 * @return {*}  {A}
	 * @memberof ReportPanelController
	 */
	public getAbility(): IPanelAbility {
		return {
			...super.getAbility(),
		};
	}
}
